package com.pisolution.scheduler.remote.codec;

import com.pisolution.scheduler.remote.command.Command;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

/**
 * 以特定的编码规则编码节点间通信传输的命令载体.
 *
 * <p></p>
 * <h3>编码规则</h3>
 * <pre>
 * +-------------------+---------+----------+-------------+---------+
 * |         8bit      |   8bit  |   64bit  |    32bit    |   ...   |
 * +-------------------+---------+----------+-------------+---------+
 * | 识别传输内容的幻数 | 命令类型 |  标识符  | 命令内容长度 | 命令内容 |
 * +-------------------+---------+----------+-------------+---------+
 * </pre>
 *
 * @author sora
 * @version 0.1.0
 */
@ChannelHandler.Sharable
public final class CommandEncoder extends MessageToByteEncoder<Command> {
    // -------------------------------------------------------------------------------------------------
    //  编码
    // -------------------------------------------------------------------------------------------------

    @Override
    protected void encode(ChannelHandlerContext ctx, Command command, ByteBuf byteBuf) throws Exception {
        // 1. 校验命令是否为空.
        if (command == null) {
            throw new Exception("The command to be encoded is null.");
        }

        // 2. 编码命令.
        byteBuf.writeByte(Command.MAGIC);
        byteBuf.writeByte(command.getType().ordinal());
        byteBuf.writeLong(command.getOpaque());
        byteBuf.writeInt(command.getBody().length);
        byteBuf.writeBytes(command.getBody());
    }
}
